﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
using Foothill.Common;
using Foothill.IoC;
using Foothill.Model;
using Foothill.Service.AdService;
using Foothill.Service.Caching;
using Foothill.Service.MiscInfo;
using Foothill.Service.Session;
using Foothill.Service.VehicleInfo;


namespace Foothill.Web
{
    public partial class ForSaleAdvancedSearch : FoothillBasePage
    {
        private IVehicleInfoService _vehicleInfoService;
        private IMiscInfoService _miscService;
        private ILocalCache _localCache;

        protected void Page_Load(object sender, EventArgs e)
        {
            _vehicleInfoService = IocContainer.GetInstance<IVehicleInfoService>();
            _miscService = IocContainer.GetInstance<IMiscInfoService>();
            _localCache = IocContainer.GetInstance<ILocalCache>();

            if (!IsPostBack)
            {
                CleanupDataInSession();
                
                ISessionService sessionService = IocContainer.GetInstance<ISessionService>();
                ForSaleAdAdvancedSearchParameter searchParam = sessionService.GetSessionValue(SessionNames.ForSaleAdvancedSearchParam) as ForSaleAdAdvancedSearchParameter;

                if (searchParam != null && !searchParam.IsDefault)
                {
                    // populate the page with the prev search param from the session
                    InitPageWithSearchParamsInSession(searchParam);
                }
                else
                {
                    // the advanced search param is not specified by users
                    InitPage();
                }
            }
        }

        private void InitPage()
        {
            // init make dropdown list
            InitMakeAndModelDropDownList();

            ddlModel.Enabled = false;
            ddlMake1.Enabled = false;
            ddlModel1.Enabled = false;
            ddlMake2.Enabled = false;
            ddlModel2.Enabled = false;
            
            InitYearDropDownLists();

            InitKilometersDropDownLists();

            InitPriceDropDownLists();

            InitLocationCheckBoxList();

            rbtBoth.Checked = true;
            rbtBothTransmission.Checked = true;
            rbtBothTypes.Checked = true;
        }

        private void InitPageWithSearchParamsInSession(ForSaleAdAdvancedSearchParameter searchParamFromSession)
        {
            if (searchParamFromSession == null)
            {
                return;
            }
            
            // make and model
            InitMakeAndModelDropDownList(searchParamFromSession);
            RangeBasedAdSearchCriteria criteria;
            
            // year
            InitYearDropDownLists();
            if (searchParamFromSession.TryGetRangeBasedCriteria(RangeBasedCriteria.YearMade, out criteria))
            {
                SafelySetDropDownSelectedValue(ddlYearFrom, criteria.Min.ToString());
                SafelySetDropDownSelectedValue(ddlYearTo, criteria.Max.ToString());
            }
            
            // mileage
            InitKilometersDropDownLists();
            if (searchParamFromSession.TryGetRangeBasedCriteria(RangeBasedCriteria.Kilometer, out criteria))
            {
                SafelySetDropDownSelectedValue(ddlKiloFrom, criteria.Min.ToString());
                SafelySetDropDownSelectedValue(ddlKiloTo, criteria.Max.ToString());
            }
            
            // price
            InitPriceDropDownLists();
            if (searchParamFromSession.TryGetRangeBasedCriteria(RangeBasedCriteria.Price, out criteria))
            {
                SafelySetDropDownSelectedValue(ddlPriceFrom, criteria.Min.ToString());
                SafelySetDropDownSelectedValue(ddlPriceTo, criteria.Max.ToString());
            }
            
            InitLocationCheckBoxList(searchParamFromSession);

            InitVehicleTypeRadioButtonGroup(searchParamFromSession);
            InitListingTypeRadioButtonGroup(searchParamFromSession);
            InitTransmissionRadioButtonGroup(searchParamFromSession);
        }

        private void InitVehicleTypeRadioButtonGroup(ForSaleAdAdvancedSearchParameter searchParamFromSession)
        {
            VehicleCondition condition = (VehicleCondition)searchParamFromSession.ConditionId;

            switch (condition)
            {
                case VehicleCondition.Both:
                    rbtBoth.Checked = true;
                    break;
                case VehicleCondition.New:
                    rbtNew.Checked = true;
                    break;
                case VehicleCondition.Used:
                    rbtUsed.Checked = true;
                    break;
                default:
                    rbtBoth.Checked = true;
                    break;
            }
        }

        private void InitListingTypeRadioButtonGroup(ForSaleAdAdvancedSearchParameter searchParamFromSession)
        {
            ListingTypes listingType = (ListingTypes)searchParamFromSession.ListingTypeId;

            switch (listingType)
            {
                case ListingTypes.Both:
                    rbtBothTypes.Checked = true;
                    break;
                case ListingTypes.Dealer:
                    rbtDealer.Checked = true;
                    break;
                case ListingTypes.Owner:
                    rbtOwner.Checked = true;
                    break;
                default:
                    rbtBothTypes.Checked = true;
                    break;
            }
        }

        private void InitTransmissionRadioButtonGroup(ForSaleAdAdvancedSearchParameter searchParamFromSession)
        {
            TransmissionType tranType = (TransmissionType)searchParamFromSession.TransmissionTypeId;

            switch (tranType)
            {
                case TransmissionType.Both:
                    rbtBothTransmission.Checked = true;
                    break;
                case TransmissionType.Automatic:
                    rbtAuto.Checked = true;
                    break;
                case TransmissionType.Manual:
                    rbtManual.Checked = true;
                    break;
                default:
                    rbtBothTransmission.Checked = true;
                    break;
            }
        }

        private void InitMakeAndModelDropDownList()
        {
            ddlMake.Items.Add(new ListItem("All", GlobalValues.AllMakeId.ToString()));
            ddlModel.Items.Add(new ListItem("All", GlobalValues.AllModelId.ToString()));
            ddlMake1.Items.Add(new ListItem("Select One", GlobalValues.IgnoreSelectedItemId.ToString()));
            ddlModel1.Items.Add(new ListItem("-", GlobalValues.IgnoreSelectedItemId.ToString()));
            ddlMake2.Items.Add(new ListItem("Select One", GlobalValues.IgnoreSelectedItemId.ToString()));
            ddlModel2.Items.Add(new ListItem("-", GlobalValues.IgnoreSelectedItemId.ToString()));

            IDictionary<int, string> makeIdNameList = _vehicleInfoService.GetVehicleMakes();

            AddItemsToDropDownList(ddlMake, makeIdNameList);
            AddItemsToDropDownList(ddlMake1, makeIdNameList);
            AddItemsToDropDownList(ddlMake2, makeIdNameList);

            ddlMake1.Enabled = false;
            ddlMake2.Enabled = false;
        }

        private void InitMakeAndModelDropDownList(ForSaleAdAdvancedSearchParameter searchParamFromSession)
        {
            if (searchParamFromSession.IncludeAllMakes)
            {
                InitMakeAndModelDropDownList();
                ddlMake.Enabled = true;

                return;
            }

            const int numOfMakeAndModelDropDownGroups = 3;

            int count = searchParamFromSession.SelectedMakeAndModelIdLookup.Count;
            IDictionary<int, string> makeIdNameList = _vehicleInfoService.GetVehicleMakes();

            for (int i = 0; i < numOfMakeAndModelDropDownGroups; ++i)
            {
                ListControl makeDropDown;
                ListControl modelDropDown;
                GetMakeAndModelDropDownListControl(i, out makeDropDown, out modelDropDown);

                if (i < count)
                {
                    MakeAndModelSelection sel = searchParamFromSession.SelectedMakeAndModelIdLookup[i];

                    AddItemsToDropDownList(makeDropDown, makeIdNameList);

                    if (i == 0)
                    {
                        // add "All" to the first make drop down
                        makeDropDown.Items.Insert(0, new ListItem("All", GlobalValues.AllMakeId.ToString()));
                    }
                    else
                    {
                        // add "Select One" to the other drop down
                        makeDropDown.Items.Insert(0, new ListItem("Select One", GlobalValues.IgnoreSelectedItemId.ToString()));
                    }

                    if (sel.Selected)
                    {
                        makeDropDown.SelectedValue = sel.MakeId.ToString();

                        IDictionary<int, string> modelDict = _vehicleInfoService.GetVehicleModels(sel.MakeId);

                        AddItemsToDropDownList(modelDropDown, modelDict);

                        // add an 'All' item to the list as the first item              
                        modelDropDown.Items.Insert(0, new ListItem("All", GlobalValues.AllModelId.ToString()));
                        modelDropDown.Enabled = true;

                        if (sel.ModelId != GlobalValues.AllModelId)
                        {
                            // a specific model
                            IsDropDownListContainValue(modelDropDown, sel.ModelId.ToString());
                            modelDropDown.SelectedValue = sel.ModelId.ToString();
                        }
                        else
                        {
                            // all models for a make
                            modelDropDown.SelectedValue = GlobalValues.AllModelId.ToString();
                        }
                    }
                }
                else
                {
                    makeDropDown.Items.Add(new ListItem("Select One", GlobalValues.IgnoreSelectedItemId.ToString()));
                    modelDropDown.Items.Add(new ListItem("-", GlobalValues.IgnoreSelectedItemId.ToString()));
                    // enable the make dropdown so users are not forced to change a prev selection when want to choose other makes/models
                    makeDropDown.Enabled = true;
                    modelDropDown.Enabled = false;
                }
            }
        }

        private void GetMakeAndModelDropDownListControl(int index, out ListControl makeDropDown, out ListControl modelDropDown)
        {
            makeDropDown = ddlMake;
            modelDropDown = ddlModel;

            switch (index)
            {
                case 1:
                    makeDropDown = ddlMake1;
                    modelDropDown = ddlModel1;
                    break;
                case 2:
                    makeDropDown = ddlMake2;
                    modelDropDown = ddlModel2;
                    break;
            }
        }

        protected void ddlMake_OnSelectedIndexChanged(Object sender, EventArgs e)
        {
            ddlModel.Items.Clear();

            int selectedMakeId = Convert.ToInt32(ddlMake.SelectedValue);

            // "All" is selected on the Make list
            if (selectedMakeId == GlobalValues.AllMakeId ) 
            {
                ddlModel.Enabled = false;
                ddlModel.Items.Insert(0, new ListItem("All", GlobalValues.AllModelId.ToString()));
                DisableMakeAndModelDropDownLists(ddlMake1, ddlModel1);
                DisableMakeAndModelDropDownLists(ddlMake2, ddlModel2);
            }
            else
            {
                // a make is selected
                IDictionary<int, string> dict = _vehicleInfoService.GetVehicleModels(selectedMakeId);

                AddItemsToDropDownList(ddlModel, dict);

                // add an 'All' item to the list as the first item              
                ddlModel.Items.Insert(0, new ListItem("All", GlobalValues.AllModelId.ToString()));

                ddlModel.Enabled = true;

                ddlMake1.Enabled = true;
                ddlMake2.Enabled = true;
            }
        }

        private void DisableMakeAndModelDropDownLists(ListControl makeDropDown, ListControl modelDropDown)
        {
            makeDropDown.SelectedIndex = 0;
            makeDropDown.Enabled = false;

            modelDropDown.Items.Clear();
            modelDropDown.Items.Add(new ListItem("-", GlobalValues.IgnoreSelectedItemId.ToString()));
            modelDropDown.Enabled = false;
        }

        protected void SecondMakeListSelectedIndexChanged(Object sender, EventArgs e)
        {
            MakeListSelectedIndexChanged(ddlMake1, ddlModel1);
        }

        protected void ThirdMakeListSelectedIndexChanged(Object sender, EventArgs e)
        {
            MakeListSelectedIndexChanged(ddlMake2, ddlModel2);
        }

        private void MakeListSelectedIndexChanged(ListControl makeDropDown, ListControl modelDropDown)
        {
            modelDropDown.Items.Clear();

            int selectedMakeId = Convert.ToInt32(makeDropDown.SelectedValue);

            // "All" is selected on the Make list
            if (selectedMakeId == GlobalValues.IgnoreSelectedItemId)
            {
                modelDropDown.Enabled = false;
                modelDropDown.Items.Insert(0, new ListItem("--", GlobalValues.IgnoreSelectedItemId.ToString()));
            }
            else
            {
                // a make is selected
                IDictionary<int, string> dict = _vehicleInfoService.GetVehicleModels(selectedMakeId);

                AddItemsToDropDownList(modelDropDown, dict);

                // add an 'All' item to the list as the first item              
                modelDropDown.Items.Insert(0, new ListItem("All", GlobalValues.AllModelId.ToString()));
                modelDropDown.Enabled = true;
            }
        }

        private void InitYearDropDownLists()
        {
            Dictionary<int, string> dict = Foothill.Common.Utility.GetYearDict();
            PopulateDropDownList(ddlYearFrom, dict);
            PopulateDropDownList(ddlYearTo, dict);

            ddlYearFrom.SelectedIndex = 3;
        }
        
        private void InitKilometersDropDownLists()
        {
            PopulateDropDownList(ddlKiloFrom, _miscService.GetMinKilometersDict());
            PopulateDropDownList(ddlKiloTo, _miscService.GetMaxKilometersDict());

            ddlKiloFrom.SelectedIndex = 3;
            ddlKiloTo.SelectedIndex = 6;
        }

        private void InitPriceDropDownLists()
        {
            PopulateDropDownList(ddlPriceFrom, _miscService.GetMinPriceDict());
            PopulateDropDownList(ddlPriceTo, _miscService.GetMaxPriceDict());

            ddlPriceFrom.SelectedIndex = 3;
            ddlPriceTo.SelectedIndex = 6;
        }

        private void InitLocationCheckBoxList()
        {
            IDictionary<int, string> dict = _miscService.GetCities((int)Provinces.BC);

            foreach (KeyValuePair<int, string> city in dict)
            {
                ListItem newItem = new ListItem(city.Value, city.Key.ToString());
                newItem.Selected = true;
                cblLocations.Items.Add( newItem );
            }
        }

        private void InitLocationCheckBoxList(ForSaleAdAdvancedSearchParameter searchParamFromSession)
        {
            IDictionary<int, string> dict = _miscService.GetCities((int)Provinces.BC);

            foreach (KeyValuePair<int, string> city in dict)
            {
                ListItem newItem = new ListItem(city.Value, city.Key.ToString());

                newItem.Selected = (searchParamFromSession.AllLocationSelected || searchParamFromSession.LocationIdList.Contains(city.Key));
                cblLocations.Items.Add(newItem);
            }
        }

        protected void btnSearch_Click(object sender, EventArgs e)
        {
            ForSaleAdAdvancedSearchParameter searchParam = ConstructSearchParameter();
            searchParam.IsDefault = false;

            ISessionService sessionService = IocContainer.GetInstance<ISessionService>();
            sessionService.AddSessionValue(SessionNames.ForSaleAdvancedSearchParam, searchParam);

            // redirect 
            Response.Redirect(string.Format("~/ForSaleList/ForSaleList.aspx?{0}={1}", GlobalQueryString.AdvSearchQsName, GlobalQueryString.AdvSearchQsValue ) );
        }

        protected void cbxSelectAllCityCheckedChanged(Object sender, EventArgs e)
        {
            bool selected = cbxSelectAllCity.Checked;
            foreach (ListItem li in cblLocations.Items)
            {
                li.Selected = selected;
            }
        }

        // check the selected makeId and change the other two accordingly
        internal void CheckSelectedMakeIdAndSetOther()
        {
            if (string.IsNullOrWhiteSpace(ddlMake.SelectedValue))
            {
                ddlMake.SelectedValue = GlobalValues.AllMakeId.ToString();
            }

            int makeId = Foothill.Common.Utility.ConvertToInt(ddlMake.SelectedValue);

            if (makeId == GlobalValues.AllMakeId)
            {
                // if All is selected in the first make dropdown
                ddlMake1.SelectedValue = GlobalValues.IgnoreSelectedItemId.ToString();
                ddlMake2.SelectedValue = GlobalValues.IgnoreSelectedItemId.ToString();
            }
        }

        // construct and validate the parameter for advanced search
        private ForSaleAdAdvancedSearchParameter ConstructSearchParameter()
        {
            ForSaleAdAdvancedSearchParameter result = new ForSaleAdAdvancedSearchParameter(_localCache.GetLocalApplicationDataDict(ApplicationDataNames.Cities).Keys.ToList());
            
            // make id and model Id
            IAdSearchService adSearchService = IocContainer.GetInstance<IAdSearchService>();

            CheckSelectedMakeIdAndSetOther();

            adSearchService.AssignMakeAndModelIds(result, Foothill.Common.Utility.ConvertToInt(ddlMake.SelectedValue), Foothill.Common.Utility.ConvertToInt(ddlModel.SelectedValue),
                Foothill.Common.Utility.ConvertToInt(ddlMake1.SelectedValue), Foothill.Common.Utility.ConvertToInt(ddlModel1.SelectedValue),
                Foothill.Common.Utility.ConvertToInt(ddlMake2.SelectedValue), Foothill.Common.Utility.ConvertToInt(ddlModel2.SelectedValue));
            
            // year 
            int from = Convert.ToInt32(ddlYearFrom.SelectedValue);
            int to = Convert.ToInt32(ddlYearTo.SelectedValue);

            result.AddRangeBasedAdSearchCriteria(RangeBasedCriteria.YearMade, (from > to) ? to : from, to);

            // kilometers
            from = Convert.ToInt32(ddlKiloFrom.SelectedValue);
            to = Convert.ToInt32(ddlKiloTo.SelectedValue);

            result.AddRangeBasedAdSearchCriteria(RangeBasedCriteria.Kilometer, (from > to) ? to : from, to);

            // price
            from = Convert.ToInt32(ddlPriceFrom.SelectedValue);
            to = Convert.ToInt32(ddlPriceTo.SelectedValue);

            result.AddRangeBasedAdSearchCriteria(RangeBasedCriteria.Price, (from > to) ? to : from, to);

            // condition
            if (rbtNew.Checked)
            {
                result.ConditionId = (int)VehicleCondition.New;
            }
            else if (rbtUsed.Checked)
            {
                result.ConditionId = (int)VehicleCondition.Used;
            }
            else
            {
                result.ConditionId = (int)VehicleCondition.Both;
            }

            // transmission type
            if (rbtAuto.Checked)
            {
                result.TransmissionTypeId = (int)TransmissionType.Automatic;
            }
            else if (rbtManual.Checked)
            {
                result.TransmissionTypeId = (int)TransmissionType.Manual;
            }
            else
            {
                result.TransmissionTypeId = (int)TransmissionType.Both;
            }

            // with photo only
            result.WithPhotosOnly = true;

            // listing type - owner or dealer
            if (rbtOwner.Checked)
            {
                result.ListingTypeId = (int)ListingTypes.Owner;
            }
            else if (rbtDealer.Checked)
            {
                result.ListingTypeId = (int)ListingTypes.Dealer;
            }
            else
            {
                result.ListingTypeId = (int)ListingTypes.Both;
            }

            // location list
            result.AddSelectedCityIdList(GetSelectedLocationList());
            result.AllLocationSelected = (result.LocationIdList.Count == cblLocations.Items.Count);

            // page size and page num
            result.PageNum = 1;
            result.PageSize = GlobalSettings.AdListPageSize;

            // order by item and directrion
            result.OrderByItem = OrderByItems.ByLastEditTime;
            result.SortDirection = fhSortDirection.DESC;

            result.FilterList = new List<AdCategorySelectItem>();
            
            return result;
        }

        // get the Id's for selected locations 
        private List<int> GetSelectedLocationList()
        {
            List<int> result = new List<int>();

            foreach (ListItem item in cblLocations.Items)
            {
                if (item.Selected)
                {
                    result.Add( Convert.ToInt32( item.Value ) );
                }
            }

            return result;
        }
    }
}
